iT邦幫忙

2021 iThome 鐵人賽

DAY 8
1
Modern Web

用30天更加認識 React.js 這個好朋友系列 第 8

Day8-React Hook 篇-認識 useMemo

  • 分享至 

  • xImage
  •  

今天介紹的是 useMemo hook,透過它可以記憶一個值。

useMemo 真的是效能優化的利器?倒也不一定,看你怎麼使用它,過度使用反而只是拖垮效能罷了

useMemo

由於當元件重新渲染時,擁有複雜計算的函式又會重複執行一次,為了避免函式又進行不必要的執行,所以透過 useMemo 將函式運算完的值存起來。像需要花比較多時間執行的複雜函式都適合使用 useMemo。

語法

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

  • 第一個參數是 callback function
  • 第二個參數是一個陣列,此陣列不作為傳到 callback function 的參數
    • useMemo(computation): 如果沒有加上這個陣列,每次都會重新執行函式去產生新的值
    • useMemo(computation, []): 空陣列的話,回傳值不會改變
    • useMemo(computation, [...someValues]): 有加上一些元素值的話,當元素值改變時會重新更新函式回傳值
  • memoizedValue 紀錄 useMemo 回傳的記憶值

特性

  1. 傳到 useMemo 的第一個參數函式會在 render 元件時執行
  2. 記憶的值不變就不會觸發重新渲染

You may rely on useMemo as a performance optimization, not as a semantic guarantee.

範例

這裡示範一下用 useMemo 去包住 Math.random() 函式,所以除了第一次渲染之外,每次印出 memoizedValue 都會出現一樣的值。

import React, { useState, useMemo } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  const memoizedValue = useMemo(() => {
    return Math.random();
  }, []);

  console.log(memoizedValue);

  return (
    <p>
      <button onClick={() => setCount(count + 1)}> Click </button>
    </p>
  );
}

程式碼範例(codesandbox)

如何去判斷當前的計算值是否值得使用 useMemo?

在 React 官方文件有提到,我們可以使用 console.timeconsole.timeEnd 去得出產生某個值出現的時間。

例如有段經過特定條件過濾的陣列 visibleTodos,我們可以用 console.timeconsole.timeEnd 去計算產生該陣列花費的時間。

console.time('filter array');
const visibleTodos = filterTodos(todos, tab);
console.timeEnd('filter array');

然後我們再加上 useMemo 去記憶該 visibleTodos,第一次渲染時當然還是會去做 filter 的動作,但之後就可以減少不必要的計算,並以此去評估是否值得去做優化。

console.time('filter array');
const visibleTodos = useMemo(() => {
  return filterTodos(todos, tab); // Skipped if todos and tab haven't changed
}, [todos, tab]);
console.timeEnd('filter array');

上一篇
Day7-在認識 useMemo 前,先認識 React.memo
下一篇
Day9-React Hook 篇-認識 useCallback
系列文
用30天更加認識 React.js 這個好朋友33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言